package com.spzx.cart.Service.Impl;

import com.spzx.cart.Service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.spzx.cart.api.domain.CartInfo;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * projectName: spzx-parent
 *
 * @author: 王宝贵
 * time: 2024/10/13 18:31 周日
 * description:
 */
@Service
public class CartServiceImpl implements ICartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RemoteProductService remoteProductService;


    /**
     * 添加购物车
     * @param skuId 商品ip
     * @param skuNum 要改变的商品的数量
     */
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //1.定义redis中大key
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //2.小key(就是skuId) 并且绑定操作对象
        BoundHashOperations<String,String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        //3.判断缓存中有数据没 是否第一次添加
         String hashKey = skuId.toString();
         Integer maxSkuNum =99;
        if(boundHashOperations.hasKey(hashKey)){
            //存在 数量加skuNum
            CartInfo cartInfo = boundHashOperations.get(hashKey);
            int redisSkuNum = cartInfo.getSkuNum() + skuNum;

            //判断是否超过最大值
            cartInfo.setSkuNum(redisSkuNum > maxSkuNum ? maxSkuNum : redisSkuNum);
            //放入到缓存里面
            boundHashOperations.put(hashKey,cartInfo);
        }else {
            //第一次添加
            //先判断购物车超过50没
            Long size = boundHashOperations.size();
            if(++size>50){
                throw new ServiceException("光吃不拉 光加不买啊");
            }
            //不是的话 根据skuId查询商品基本信息 封装到cat对象 放到redis缓存中
            CartInfo cartInfo = new CartInfo();
            R<ProductSku> productSkuR = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if(productSkuR.getCode()==R.FAIL){
                throw new ServiceException("添加购物车查询数据降级:"+productSkuR.getMsg());
            }
            ProductSku productSku = productSkuR.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setUserId(userId);
            cartInfo.setCartPrice(productSku.getSalePrice());
            cartInfo.setSkuPrice(productSku.getSalePrice());
            cartInfo.setCreateTime(new Date());
            //库存
            cartInfo.setSkuNum(skuNum>maxSkuNum? maxSkuNum:skuNum);
            cartInfo.setThumbImg(productSku.getThumbImg()); //加入到redis缓存中的两种都是一样的 在购物车查询的时候 更新价格
            cartInfo.setSkuName(productSku.getSkuName());
          //  cartInfo.setIsChecked(); 是否可以在购物车显示 暂时不加

            //存到redis中
            boundHashOperations.put(hashKey,cartInfo);

        }

    }



    /**
     * 查询购物车 加更新价格
     * @return
     */
    @Override
    public List<CartInfo> getCartList() {
        //获取登陆者的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        //从缓存中获取数据
        List<CartInfo> cartInfoList = boundHashOperations.values();
//        List<CartInfo>  cartInfoList= redisTemplate.opsForHash().values(cartKey);
        //按照添加的时间顺序倒序排序
        if(!CollectionUtils.isEmpty(cartInfoList)){
            List<CartInfo> infoList = cartInfoList.stream()
                    .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
                    .collect(Collectors.toList());
            //更新价格
            // 将CarInfo 提出skuId一个集合
            // 先从数据库获取最新的数据 用skuId集合
            // 再将数据装为map key 为skuId value为最新价格
            // 遍历info集合 为每一个CartInfo赋值最新的价格
            List<Long> skuIdList = infoList.stream().map(CartInfo::getSkuId).collect(Collectors.toList());
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if(skuPriceList.getCode()==R.FAIL){
                throw  new ServiceException("批量查询价格降级了："+skuPriceList.getMsg());
            }
            Map<Long, BigDecimal> salePriceMap = skuPriceList.getData().stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            infoList.forEach(item->{
                //设置实时价格
                item.setSkuPrice(salePriceMap.get(item.getSkuId()));
            });

            return cartInfoList;
        }

        return new ArrayList<CartInfo>();
    }


    /**
     * 删除购物车的信息
     * @param skuId 商品的id
     */
    @Override
    public void delectCart(Long skuId) {
        //获取登陆者的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOps = redisTemplate.boundHashOps(cartKey);
        //删除--记得将skuId字符串化
        boundHashOps.delete(skuId.toString());
    }
    

    /**
     * 更改购物车状态
     * @param skuId
     * @param isChecked 1.选中 0取消选中
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //获取登陆者的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOps = redisTemplate.boundHashOps(cartKey);
        // 更改状态
        //通过小key获取 单个
        CartInfo cartInfo = boundHashOps.get(skuId.toString());
        //通过values获取所有
        List<CartInfo> values = boundHashOps.values();
        cartInfo.setIsChecked(isChecked);
        //放到缓存里面
        boundHashOps.put(skuId.toString(),cartInfo);

    }


    /**
     * 更新购物车商品全部选中状态
     * @param isChecked
     */
    @Override
    public void allCheckCart(Integer isChecked) {
        //获取登陆者的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOps.values();
        cartInfoList.forEach(cartInfo -> {
        //    CartInfo cartInfoUpd = boundHashOps.get(cartInfo.getSkuId().toString());
            cartInfo.setIsChecked(isChecked);

            //更新缓存
            boundHashOps.put(cartInfo.getSkuId().toString(),cartInfo);
        });

    }

    //清空购物车
    @Override
    public void clearCart() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        redisTemplate.delete(cartKey);
    }

    /**
     * 查询用户购物车列表中选中商品列表
     * @param userId 用户id
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //新建一个空的 方便返回去
        List<CartInfo> cartInfoList = new ArrayList<>();

        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfosList = boundHashOps.values();
        if(!CollectionUtils.isEmpty(cartInfosList)){
            cartInfosList.forEach(cartInfo -> {
                //获取选中的商品
                if(cartInfo.getIsChecked().intValue() ==1){
                    cartInfoList.add(cartInfo);
                }
            });
        }

        return cartInfosList;
    }


    /**
     * 更新用户购物车列表价格
     * @param userId 用户id
     * @return
     */
    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        //从换缓存中获取的价格
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            //从数据库中获取数据
            List<Long> skuIdList = cartInfoList.stream().map(cartInfo -> cartInfo.getSkuId()).toList();
            R<List<SkuPrice>> skuPriceList = remoteProductService.getSkuPriceList(skuIdList,SecurityConstants.INNER);
            if(skuPriceList.getCode() ==R.FAIL){
                throw new ServiceException("从数据库获取最新价格服务降级："+skuPriceList.getMsg());
            }
            List<SkuPrice> skuPriceListData = skuPriceList.getData();
            //变成map集合
            Map<Long, BigDecimal> skuIdToSalePriceMap = skuPriceListData.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            cartInfoList.forEach(cartInfo -> {
                if(cartInfo.getIsChecked() ==1){
                    //更新缓存
                    cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
                    cartInfo.setCartPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
                    cartInfo.setUpdateTime(new Date());
                    boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
                }

            });
        }
        return true;
    }

    /**
     * 删除用户购物车列表中选中商品列表
     * @param userId 用户id
     * @return
     */
    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        cartInfoList.forEach(cartInfo -> {
            if(cartInfo.getIsChecked()==1){
                boundHashOperations.delete(cartInfo.getSkuId().toString());
            }
        });
        return true;
    }

    private String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }
}